home *** CD-ROM | disk | FTP | other *** search
- /* amiga/ui.c
- vi:ts=3 sw=3:
- */
-
- /* $Id: ui.c,v 1.22 1995/02/14 16:51:22 espie Exp espie $
- * $Log: ui.c,v $
- * Revision 1.22 1995/02/14 16:51:22 espie
- * *** empty log message ***
- *
- * Revision 1.21 1995/02/13 22:05:42 espie
- * Changed version number.
- *
- * Revision 1.20 1995/01/13 13:31:35 espie
- * *** empty log message ***
- *
- * Revision 1.20 1994/06/22 21:54:12 Espie
- * Split across other files.
- * File requester !
- * Added pause gadget.
- * Uncentralized event handling using event management functions.
- * Changed name to ui_win, added Show gadget.
- * better coding for gadgets.
- * Nasty bug with info: did not close the file properly.
- * Fully working asynchronous interface.
- * User feedback.
- * Added missing autoinit
- * Removed some typecasts.
- * info facility.
- * scroll post-synchronized output.
- * notice.
- * Cursor handling.
- * Used of discard_buffer for premature ending.
- * Mostly working.
- * Just dies with a guru.
- * Plus timing problems at start.
- */
-
- #include <proto/intuition.h>
- #include <proto/gadtools.h>
- #include <proto/exec.h>
- #include <dos/dos.h>
- #include <intuition/intuitionbase.h>
-
- #include "defs.h"
- #include "version.h"
- #include "extern.h"
- #include "amiga/amiga.h"
- #include "tags.h"
- #include "prefs.h"
-
- ID("$Id: ui.c,v 1.22 1995/02/14 16:51:22 espie Exp espie $")
-
- XT unsigned int inhibit_output;
-
- LOCAL void init_ui(void);
- LOCAL void do_set_current(VALUE current);
- LOCAL void handle_ui_window(GENERIC nothing);
-
- LOCAL void (*INIT)(void) = init_ui;
-
-
- /* These two variables memorize where we actually are in
- * the current song
- */
- LOCAL int current_pattern;
-
- #define SMALL_DELAY 3 /* in seconds */
-
- /* And these when stuff last changed */
- LOCAL ULONG pattern_change_seconds, pattern_change_micros,
- song_change_seconds, song_change_micros;
-
-
- /* The basic user interface (a simple window) */
-
- struct IntuitionBase *IntuitionBase = 0;
- struct GfxBase *GfxBase = 0;
- LOCAL struct Library *GadtoolsBase = 0;
- LOCAL struct Window *ui_win;
-
- void set_busy_pointer(BOOL maybe)
- {
- if (IntuitionBase->LibNode.lib_Version < 39)
- return;
- if (ui_win)
- SetWindowPointer(ui_win, WA_BusyPointer, maybe, WA_PointerDelay, TRUE, TAG_DONE, 0);
- }
-
- /* for asynchronous easy requests */
- LOCAL struct Window *notice_win = 0;
-
- /* for computing length */
- LOCAL struct IntuiText it;
-
- #define SHIFT 4
- #define SPACEX 10
- #define SPACEY 4
-
- #define WINDOW_TITLE "Experiment IV " /* the space in case the font is italic */
-
- LOCAL struct NewGadget template =
- {
- 0, 0,
- 0, 0,
- NULL,
- 0,
- 0, /* gadget ID */
- 0,
- NULL,
- NULL
- };
-
- LOCAL struct NewMenu menu_template[] =
- {
- {NM_TITLE, "Project", 0, 0, 0, 0},
- {NM_ITEM, "Load song...", 0, 0, 0, (void *)4},
- {NM_ITEM, "About...", 0, 0, 0, (void *)1},
- {NM_ITEM, "Quit", 0, 0, 0, (void *)2},
- {NM_TITLE, "Settings", 0, 0, 0, 0},
- /* WARNING: check item_number if you add menu entries */
- {NM_ITEM, "PAL", 0, CHECKIT, 6, (void *)50},
- {NM_ITEM, "NTSC", 0, CHECKIT, 5, (void *)60},
- {NM_ITEM, "Custom", 0, CHECKIT, 3, (void *)3},
- {NM_END, 0, 0, 0, 0, 0}
- };
-
- LOCAL struct Menu *menu = 0;
-
- LOCAL APTR vi;
- LOCAL struct Screen *pub = 0;
- LOCAL struct Gadget *glist, *title_gad, *pattern_gad, *total_gad;
-
- /* we precisely have seven gadgets */
- #define MAX_GADGET 6
-
- /* all labelled with strings */
- LOCAL char *label[MAX_GADGET + 1] =
- {
- "|<",
- "<<",
- "//",
- ">>",
- ">|",
- "?",
- "000",
- };
-
- #define G_NEXT 4
- #define G_RESTART_PREVIOUS 0
- #define G_REWIND 1
- #define G_FF 3
- #define G_SHOW 5
- #define G_PAUSE 2
- LOCAL struct ext_message *restart_msg = NULL;
-
- LOCAL void cleanup_ui()
- {
- if (restart_msg)
- {
- send(restart_msg, TYPE_UNPAUSE);
- restart_msg = 0;
- }
- if (ui_win)
- {
- remove_signal_handler(ui_win->UserPort->mp_SigBit);
- SetWindowTitles(ui_win, 0, 0);
- ClearMenuStrip(ui_win);
- CloseWindow(ui_win);
- ui_win = 0;
- }
- if (menu)
- FreeMenus(menu);
- if (glist)
- FreeGadgets(glist);
- if (vi)
- FreeVisualInfo(vi);
- if (pub)
- UnlockPubScreen(NULL, pub);
- while (notice_win)
- await_events();
- if (GfxBase)
- CloseLibrary(GfxBase);
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- if (GadtoolsBase)
- CloseLibrary(GadtoolsBase);
- }
-
-
- LOCAL void init_ui(void)
- {
- struct Gadget *gad;
- int i;
- int max_width;
- int width, height;
- UWORD zoom[4];
-
- at_end(cleanup_ui);
- IntuitionBase = OpenLibrary("intuition.library", 37);
- if (!IntuitionBase)
- end_all("No Intuition");
- GadtoolsBase = OpenLibrary("gadtools.library", 37);
- if (!GadtoolsBase)
- end_all("No gadtools");
- GfxBase = OpenLibrary("graphics.library", 37);
- if (!GfxBase)
- end_all("No graphics");
- pub = LockPubScreen(NULL);
- if (!pub)
- end_all("No pubscreen");
- vi = GetVisualInfo(pub, TAG_END);
- if (!vi)
- end_all("No VI");
- {
- int item_number;
-
- switch(get_pref_scalar(PREF_SPEED))
- {
- case 50:
- item_number = 5; break;
- case 60:
- item_number = 6; break;
- default:
- item_number = 7; break;
- }
- menu_template[item_number].nm_Flags |= CHECKED;
- }
- menu = CreateMenus(menu_template, GTMN_FrontPen, BARDETAILPEN, TAG_END);
- if (!menu)
- end_all("No menus");
- if (!LayoutMenus(menu, vi, TAG_END))
- end_all("Menus badly formed");
-
- /* now to create the gadgets */
- /* Compute max width/height according to the font */
- it.ITextFont = pub->Font;
- template.ng_TextAttr = pub->Font;
-
- max_width = 0;
- for (i = 0; i < MAX_GADGET + 1; i++)
- {
- it.IText = label[i];
- width = IntuiTextLength(&it);
- if (width > max_width)
- max_width = width;
- }
-
- max_width += SPACEX;
- template.ng_Width = max_width;
- template.ng_Height = pub->Font->ta_YSize + SPACEY;
-
- /* set up Top/Left Edge of initial gadget according to Wbar */
- template.ng_TopEdge = pub->WBorTop + 1 + 2 * template.ng_Height + SHIFT;
- template.ng_LeftEdge = pub->WBorLeft + SHIFT;
-
- gad = CreateContext(&glist);
- if (!gad)
- end_all("No context");
- template.ng_VisualInfo = vi;
- /* lay out gadgets */
- for (i = 0; i < MAX_GADGET; i++)
- {
- template.ng_GadgetText = label[i];
- gad = CreateGadget(BUTTON_KIND, gad, &template, TAG_END);
- if (!gad)
- end_all("Bad gadget");
- template.ng_LeftEdge += template.ng_Width + SHIFT;
- template.ng_GadgetID++;
- }
- width = template.ng_LeftEdge + pub->WBorRight;
- height = template.ng_TopEdge + template.ng_Height + pub->WBorBottom + SHIFT;
-
- /* zoom box */
- zoom[0] = ~0;
- zoom[1] = ~0;
- zoom[2] = width;
- zoom[3] = pub->WBorTop + 1 + pub->Font->ta_YSize;
-
- /* title gadget */
- template.ng_GadgetText = "";
- template.ng_Width = width - SHIFT - pub->WBorLeft - pub->WBorRight;
- template.ng_Width -= 2 * max_width;
- template.ng_TopEdge = pub->WBorTop + 1 + template.ng_Height + SHIFT;
- template.ng_LeftEdge = SHIFT + pub->WBorLeft;
- title_gad = gad = CreateGadget(TEXT_KIND, gad, &template, TAG_END);
- if (!gad)
- end_all("Bad gadget");
-
- /* pattern gadget */
- template.ng_LeftEdge += template.ng_Width + SHIFT;
- template.ng_Width = max_width;
- pattern_gad = gad = CreateGadget(NUMBER_KIND, gad, &template, TAG_END);
- if (!gad)
- end_all("Bad gadget");
-
- /* total pattern */
- template.ng_GadgetText = "/";
- template.ng_LeftEdge += template.ng_Width + SHIFT;
- total_gad = gad = CreateGadget(NUMBER_KIND, gad, &template, TAG_END);
- if (!gad)
- end_all("Bad gadget");
- ui_win = OpenWindowTags(NULL,
- WA_Title, WINDOW_TITLE,
- WA_Width, width,
- WA_Height, height,
- WA_MinWidth, zoom[2],
- WA_MaxWidth, width,
- WA_MinHeight, zoom[3],
- WA_MaxHeight, height,
- WA_AutoAdjust, TRUE,
- WA_MouseQueue, 35, /* we can't always answer messages */
- WA_DepthGadget, TRUE,
- WA_CloseGadget, TRUE,
- WA_DragBar, TRUE,
- WA_Zoom, zoom,
- WA_Gadgets, glist,
- WA_IDCMP, IDCMP_CLOSEWINDOW | BUTTONIDCMP | TEXTIDCMP |
- IDCMP_REFRESHWINDOW | IDCMP_MENUPICK,
- WA_NewLookMenus, TRUE,
- WA_PubScreen, pub,
- TAG_DONE, 0);
- if (!ui_win)
- end_all("No window");
- GT_RefreshWindow(ui_win, NULL);
- SetMenuStrip(ui_win, menu);
-
- install_signal_handler(ui_win->UserPort->mp_SigBit, handle_ui_window, 0);
-
- /* build up scroll buffer stuff */
- }
-
- struct Screen *obtain_pubscreen(void)
- {
- INIT_ONCE;
-
- return pub;
- }
-
- /* Max number of input messages we can remember */
- #define MAX_INPUT 20
- LOCAL struct tag result[MAX_INPUT +1];
- LOCAL int i = 0;
-
- LOCAL void handle_ui_window(GENERIC nothing)
- {
- struct IntuiMessage *msg;
- UWORD number;
- struct MenuItem *item;
- int id;
- VALUE temp;
-
- while((msg = GT_GetIMsg(ui_win->UserPort)) && i < MAX_INPUT)
- switch(msg->Class)
- {
- case IDCMP_CLOSEWINDOW:
- GT_ReplyIMsg(msg);
- set_break();
- break;
- case IDCMP_MENUPICK:
- number = msg->Code;
- while (number != MENUNULL)
- {
- item = ItemAddress(menu, msg->Code);
- switch((int)GTMENUITEM_USERDATA(item))
- {
- case 1:
- notice(
- "Tracker "VERSION"\n\
- by Marc Espie (Marc.Espie@ens.fr)\n\n\
- This is a giftware program\n\
- If you want, you can send me some money\n\
- My address is:\n\
- Espie Marc\n\
- 60 rue du 4 septembre\n\
- 87100 Limoges\n\
- France\n\n\
- For the most recent version:\n\
- ftp Aminet or nic.funet.fi");
- break;
- case 2:
- item = 0;
- set_break();
- break;
- case 4:
- launch_requester();
- break;
- case 50:
- case 60:
- result[i].type = UI_SET_BPM;
- result[i++].data.scalar = (int)GTMENUITEM_USERDATA(item);
- set_pref_scalar(PREF_SPEED, (int)GTMENUITEM_USERDATA(item));
- break;
- default:
- break;
- }
- number = item->NextSelect;
- }
- GT_ReplyIMsg(msg);
- break;
- case IDCMP_REFRESHWINDOW:
- GT_ReplyIMsg(msg);
- GT_BeginRefresh(ui_win);
- GT_EndRefresh(ui_win, TRUE);
- break;
- case IDCMP_GADGETUP:
- id = ((struct Gadget *)msg->IAddress)->GadgetID;
- switch(id)
- {
- case G_NEXT:
- result[i++].type = UI_NEXT_SONG;
- break;
- case G_RESTART_PREVIOUS:
- if (msg->Seconds < song_change_seconds + SMALL_DELAY ||
- (msg->Seconds == song_change_seconds + SMALL_DELAY &&
- msg->Micros <= song_change_micros) )
- {
- result[i++].type = UI_PREVIOUS_SONG;
- break;
- }
- else
- {
- result[i++].type = UI_RESTART;
- song_change_seconds = msg->Seconds;
- song_change_micros = msg->Micros;
- }
- break;
- case G_REWIND:
- result[i].type = UI_JUMP_TO_PATTERN;
- result[i].data.scalar = current_pattern;
- if (msg->Seconds < pattern_change_seconds + SMALL_DELAY ||
- (msg->Seconds == pattern_change_seconds + SMALL_DELAY &&
- msg->Micros <= pattern_change_micros) )
- result[i].data.scalar--;
- /* give some immediate feedback to the user */
- temp.scalar = result[i].data.scalar;
- do_set_current(temp);
- i++;
- break;
- case G_FF:
- result[i].type = UI_JUMP_TO_PATTERN;
- result[i].data.scalar = current_pattern + 1;
- /* give some immediate feedback to the user */
- temp.scalar = result[i].data.scalar;
- do_set_current(temp);
- i++;
- break;
- case G_SHOW:
- set_pref_scalar(PREF_SHOW, TRUE);
- break;
- case G_PAUSE:
- if (restart_msg)
- {
- send(restart_msg, TYPE_UNPAUSE);
- restart_msg = 0;
- }
- else
- {
- struct ext_message *msg;
-
- msg = obtain_message();
- restart_msg = obtain_message();
- send(msg, TYPE_PAUSE);
- }
- }
- GT_ReplyIMsg(msg);
- break;
- default:
- GT_ReplyIMsg(msg);
- }
- }
-
-
- void requested_file(struct amiganame *name)
- {
- result[i].data.pointer = name;
- result[i++].type = UI_LOAD_SONG;
- }
-
-
- struct tag *get_ui()
- {
-
- INIT_ONCE
-
- if (checkbrk())
- result[i++].type = UI_QUIT;
-
- result[i].type = TAG_END;
-
- i = 0;
- return result;
- }
-
-
- void song_title(char *s)
- {
- static char title[25];
-
- INIT_ONCE;
-
- strncpy(title, s, 25);
- if (ui_win)
- GT_SetGadgetAttrs(title_gad, ui_win, 0, GTTX_Text, title, TAG_END);
- /* stamp the time we changed the song */
- CurrentTime(&song_change_seconds, &song_change_micros);
- }
-
- void status(char *s)
- {
- INIT_ONCE;
-
- SetWindowTitles(ui_win, s ? s : WINDOW_TITLE, -1);
- }
-
- /* hook to change current pattern */
- LOCAL void do_set_current(VALUE p)
- {
- if (!inhibit_output)
- {
- INIT_ONCE;
- if (ui_win)
- GT_SetGadgetAttrs(pattern_gad, ui_win, 0, GTNM_Number, p.scalar, TAG_END);
- }
- current_pattern = p.scalar;
- /* stamp the time we changed the pattern */
- CurrentTime(&pattern_change_seconds, &pattern_change_micros);
- }
-
- /* hook to change current pattern total */
- LOCAL void do_set_total(VALUE p)
- {
- INIT_ONCE;
- if (ui_win)
- GT_SetGadgetAttrs(total_gad, ui_win, 0, GTNM_Number, p.scalar, TAG_END);
- }
-
- void display_pattern(int current, int total, int real)
- {
- struct ext_message *msg;
-
- INIT_ONCE
-
- msg = obtain_message();
- msg->data.hook.func = do_set_total;
- msg->data.hook.p.scalar = total;
- send(msg, TYPE_SYNC_DO);
-
- msg = obtain_message();
- msg->data.hook.func = do_set_current;
- msg->data.hook.p.scalar = current;
- send(msg, TYPE_SYNC_DO);
- }
-
-
-
-
- /***
- ***
- *** notice() pseudo-system call.
- *** mostly used to report errors
- ***
- *** The only difficulty comes from the fact
- *** that we may be called under any kind of environment
- ***
- ***/
-
- #ifdef USE_ARQ
- #include "arq.h"
- /* arq 1.78 doesn't notice BuildEasyRequest().
- I need to contact Martin Laubach about it
- FidoNet: 2:310/3.14
- Usenet: mjl@alison.at (home)
- mjl@auto.tuwien.ac.at (work)
- {cbmvax!cbmehq,mcsun!tuvie}!cbmvie!alison!mjl
-
- Peter, the graphics and animation wizard, can be reached
- 2:310/42 in FidoNet.
- */
-
- LOCAL struct ExtEasyStruct es =
- {
- 0,
- 0,
- ARQ_ID_INFO,
- 0,
- ARQ_MAGIC,
- 0, 0, 0,
- sizeof(struct EasyStruct),
- 0,
- "Notice\xa0",
- NULL,
- "Proceed"
- };
- LOCAL struct EasyStruct *esp = & (es.Easy);
- #else
- LOCAL struct EasyStruct es =
- {
- sizeof(struct EasyStruct),
- 0,
- "Notice",
- NULL,
- "Proceed"
- };
- LOCAL struct EasyStruct *esp = &es;
- #endif
-
-
- void handle_notice(struct Window *w)
- {
- if (SysReqHandler(w, 0, FALSE) != -2)
- {
- remove_signal_handler(w->UserPort->mp_SigBit);
- FreeSysRequest(w);
- notice_win = 0;
- }
- }
-
- void notice(char *s)
- {
- INIT_ONCE;
-
- if (!IntuitionBase)
- {
- fprintf(stderr, s);
- fputc('\n', stderr);
- }
- else
- {
- /* wait for previous notice to go away */
- while (notice_win)
- await_events();
-
- esp->es_TextFormat = s;
- notice_win = BuildEasyRequest(0, esp, NULL, NULL);
- install_signal_handler(notice_win->UserPort->mp_SigBit, handle_notice, notice_win);
- }
- }
-
-